/*
 * Cratos Tools - Data Access
 * Cratos Data Access class
 * 
 * Copyright (c) 2011-2012 Draco
 * 
 * This file is part of Cratos.
 * 
 * Cratos is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * Cratos is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Cratos.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *       .==.        .==.
 *      //'^\\      //^'\\
 *     // ^ ^\(\__/)/^ ^^\\
 *    //^ ^^ ^/6  6\ ^^ ^ \\
 *   //^ ^^ ^/( .. )\^ ^ ^ \\
 *  // ^^ ^/\| V""V|/\^ ^ ^ \\
 * //^^/\/ /  '~~'  \ \/\^ ^ \\
 *  ------------------------------------
 *  HERE BE DRAGONS
 *  
 *  Johan Dercksen - johan@draco.co.za
 */
using System;
using System.Text;
using System.Data;
using System.Data.Odbc;
using System.Data.Common;
using System.Globalization;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using System.Collections.Generic;

using Cratos.Tools.General;

namespace Cratos.Tools.DataAccess
{
	/// <summary>
	/// Cratos Data Access Base class
	/// </summary>
	public abstract class CratosDataAccess : ICratosDataAccess, IDisposable
	{
		#region Class Constant declarations
		/// <summary>
		/// Unsupported database type error message
		/// </summary>
		/// <remarks>
		/// This constant contains the unsupported database type error message
		/// </remarks>
		public const string ErrorDBUnsupported = "Database Type is not supported";
		#endregion

		#region Class Variable declarations
		private bool									isDisposed;
		private bool									useTransaction;
		private CratosDatabaseType		databaseType			= CratosDatabaseType.SqlServer;
		private DOCratosActionType		dbActionType			= DOCratosActionType.StoredProcedure;
		private CratosDatabaseResult	databaseResult		= CratosDatabaseResult.Success;
		private string								connectionString	= "";
		private int										commandTimeout		= 120;

		private SqlConnection					sqlConnection;
		private OdbcConnection				odbcConnection;
		private SqlCeConnection				sqlCeConnection;

		private SqlCommand						sqlCommand;
		private OdbcCommand						odbcCommand;
		private SqlCeCommand					sqlCeCommand;

		private SqlDataReader					sqlDataReader;
		private OdbcDataReader				odbcDataReader;
		private SqlCeDataReader				sqlCeDataReader;
		#endregion

		#region Class Constructors & Destructors
		/// <summary>
		/// Class Constructor
		/// </summary>
		protected CratosDataAccess() { }

		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or
		/// resetting unmanaged resources.
		/// </summary>
		public virtual void Dispose() { Dispose(true); GC.SuppressFinalize(this); }

		/// <summary>
		/// Dispose method doing the disposing
		/// </summary>
		/// <param name="isDisposing"></param>
		protected virtual void Dispose(bool isDisposing)
		{
			// Declare the required variables

			// Check to see if Dispose has already been called.
			if (!this.isDisposed)
			{
				// Dispose the objects if required
				if (isDisposing)
				{
					// Dispose the relevant Connection objects
					if (this.sqlConnection != null) { this.sqlConnection.Dispose(); this.sqlConnection = null; }
					if (this.odbcConnection != null) { this.odbcConnection.Dispose(); this.odbcConnection = null; }
					if (this.sqlCeConnection != null) { this.sqlCeConnection.Dispose(); this.sqlCeConnection= null; }

					// Dispose the relevant Data Reader objects
					if (this.sqlDataReader != null) { this.sqlDataReader.Dispose(); this.sqlDataReader = null; }
					if (this.odbcDataReader != null) { this.odbcDataReader.Dispose(); this.odbcDataReader = null; }
					if (this.sqlCeDataReader != null) { this.sqlCeDataReader.Dispose(); this.sqlCeDataReader = null; }

					// Dispose the relevant Command objects
					if (this.sqlCommand != null) { this.sqlCommand.Dispose(); this.sqlCommand = null; }
					if (this.odbcCommand != null) { this.odbcCommand.Dispose(); this.odbcCommand = null; }
					if (this.sqlCeCommand != null) { this.sqlCeCommand.Dispose(); this.sqlCeCommand = null; }
				}
			}

			// Set the disposed indicator
			this.isDisposed = true;

			// Return to calling method
			return;
		}
		#endregion

		#region Class Properties
		/// <summary>
		/// Database Type
		/// </summary>
		public CratosDatabaseType DatabaseType
		{
			get { return (this.databaseType); }
			set { this.databaseType = value; this.SetupConnection(); }
		}
		
		/// <summary>
		/// Command Type
		/// </summary>
		public DOCratosActionType DBActionType
		{
			get { return (this.dbActionType); }
			set
			{
				// Save the new value
				this.dbActionType = value;

				// Handle the relevant database type
				switch (this.dbActionType)
				{
					case DOCratosActionType.StoredProcedure:
						this.Command.CommandType = CommandType.StoredProcedure;
						break;

					case DOCratosActionType.SqlString:
						this.Command.CommandType = CommandType.Text;
						break;
				}
			}
		}

		/// <summary>
		/// Command Text
		/// </summary>
		public string DBActionText
		{
			get { return (this.Command.CommandText); }
			set { this.Command.CommandText = value; }
		}

		/// <summary>
		/// Command Timeout
		/// </summary>
		public int CommandTimeout
		{
			get { return (this.commandTimeout); }
			set { this.commandTimeout = value; }
		}

		/// <summary>
		/// Connection String
		/// </summary>
		public string ConnectionString
		{
			get { return (this.connectionString); }
			set { this.connectionString = value; this.SetupConnection(); }
		}

		/// <summary>
		/// Connection Object
		/// </summary>
		public IDbConnection Connection
		{
			get
			{
				// Handle the relevant Database type
				switch (this.databaseType)
				{
					case CratosDatabaseType.SqlServer:
						// Make sure we have setup the connection
						if (this.sqlConnection == null) { this.SetupConnection(); }

						// Return the SQL connection
						return (this.sqlConnection);

					case CratosDatabaseType.Odbc:
						// Make sure we have setup the connection
						if (this.odbcConnection == null) { this.SetupConnection(); }

						// Return the ODBC connection
						return (this.odbcConnection);

					case CratosDatabaseType.SqlCeServer:
						// Make sure we have setup the connection
						if (this.sqlCeConnection == null) { this.SetupConnection(); }

						// Return the SQL Server CE connection
						return (this.sqlCeConnection);

					default:
						return (null);
				}
			}
			set
			{
				// Handle the relevant Database type
				switch (this.databaseType)
				{
					case CratosDatabaseType.SqlServer:
						// Save the relevant connection
						this.sqlConnection = (SqlConnection)value;
						break;

					case CratosDatabaseType.Odbc:
						// Save the relevant connection
						this.odbcConnection = (OdbcConnection)value;
						break;

					case CratosDatabaseType.SqlCeServer:
						// Save the relevant connection
						this.sqlCeConnection = (SqlCeConnection)value;
						break;
				}
			}
		}

		/// <summary>
		/// Command Object
		/// </summary>
		public DbCommand Command
		{
			get
			{
				// Handle the relevant Database type
				switch (this.databaseType)
				{
					case CratosDatabaseType.SqlServer:
						// Make sure we have setup the relevant command
						if (this.sqlCommand == null) { this.SetupCommand(); }

						// Return the relevant command object
						return (this.sqlCommand);

					case CratosDatabaseType.Odbc:
						// Make sure we have setup the relevant command
						if (this.odbcCommand == null) { this.SetupCommand(); }

						// Return the relevant command object
						return (this.odbcCommand);

					case CratosDatabaseType.SqlCeServer:
						// Make sure we have setup the relevant command
						if (this.sqlCeCommand == null) { this.SetupCommand(); }

						// Return the relevant command object
						return (this.sqlCeCommand);

					default:
						return (null);
				}
			}
		}

		/// <summary>
		/// Use Transactional support
		/// </summary>
		public bool UseTransaction
		{
			get { return (this.useTransaction); }
			set { this.useTransaction = value; }
		}

		/// <summary>
		/// Data Reader
		/// </summary>
		public IDataReader DataReader
		{
			get
			{
				// Handle the relevant database type
				switch (this.DatabaseType)
				{
					case CratosDatabaseType.SqlServer:
						// Return the SQL Data Reader
						return (this.sqlDataReader);

					case CratosDatabaseType.Odbc:
						// Return the ODBC Data Reader
						return (this.odbcDataReader);

					case CratosDatabaseType.SqlCeServer:
						// Return the SQL Server CE Data Reader
						return (this.sqlCeDataReader);

					default:
						return (null);
				}
			}
		}

		/// <summary>
		/// Reader contains data
		/// </summary>
		public bool ReaderHasRows
		{
			get
			{
				// Declare the required variables
				bool returnValue = false;

				// Handle the relevant database type
				switch (this.DatabaseType)
				{
					case CratosDatabaseType.SqlServer:
						// Make sure we have data to work with
						if (this.sqlDataReader != null) { returnValue = this.sqlDataReader.HasRows; }
						break;

					case CratosDatabaseType.Odbc:
						// Make sure we have data to work with
						if (this.odbcDataReader != null) { returnValue = this.odbcDataReader.HasRows; }
						break;

					case CratosDatabaseType.SqlCeServer:
						// Make sure we have data to work with
						if (this.sqlCeDataReader != null) { returnValue = this.sqlCeDataReader.HasRows; }
						break;
				}

				// Return to calling method
				return (returnValue);
			}
		}

		/// <summary>
		/// Database Result
		/// </summary>
		public CratosDatabaseResult Result
		{
			get { return (this.databaseResult); }
		}
		#endregion

		#region Class Methods
		/// <summary>
		/// Database Connect
		/// </summary>
		/// <remarks>
		/// This method makes use of the connection properties to open a connection to
		/// the database required.
		/// </remarks>
		/// <returns>
		/// A boolean value is returned indicating the success of the method
		/// </returns>
		public bool Connect()
		{
			// Declare the required variables
			bool returnValue = false;

			// Handle the relevant database type
			switch (this.databaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have a connection
					if (this.sqlConnection == null) { this.SetupConnection(); }

					// Determine if the connection is already open
					if (this.sqlConnection.State != ConnectionState.Open)
					{
						// Open the connection to the server
						this.sqlConnection.Open();
					}

					// Set the return value
					returnValue = (this.sqlConnection.State == ConnectionState.Open);

					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have a connection
					if (this.odbcConnection == null) { this.SetupConnection(); }

					// Determine if the connection is already open
					if (this.odbcConnection.State != ConnectionState.Open)
					{
						// Open the connection to the server
						this.odbcConnection.Open();
					}

					// Set the return value
					returnValue = (this.odbcConnection.State == ConnectionState.Open);

					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have a connection
					if (this.sqlCeConnection == null) { this.SetupConnection(); }

					// Determine if the connection is already open
					if (this.sqlCeConnection.State != ConnectionState.Open)
					{
						// Open the connection to the server
						this.sqlCeConnection.Open();
					}

					// Set the return value
					returnValue = (this.sqlCeConnection.State == ConnectionState.Open);

					break;

				default:
					throw new Exception(ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Database Disconnect
		/// </summary>
		/// <remarks>
		/// This method closes a previously opened connection.
		/// </remarks>
		/// <returns>
		/// A boolean value is returned indicating the success of the method
		/// </returns>
		public void Disconnect()
		{
			// Declare the required variables

			// Handle the relevant database type
			switch (this.databaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Determine whether the connection is open
					if (this.sqlConnection.State != ConnectionState.Closed)
					{
						// Close the connection
						this.sqlConnection.Close();
					}

					break;

				case CratosDatabaseType.Odbc:
					// Determine whether the connection is open
					if (this.odbcConnection.State != ConnectionState.Closed)
					{
						// Close the connection
						this.odbcConnection.Close();
					}

					break;

				case CratosDatabaseType.SqlCeServer:
					// Determine whether the connection is open
					if (this.sqlCeConnection.State != ConnectionState.Closed)
					{
						// Close the connection
						this.sqlCeConnection.Close();
					}

					break;

				default:
					throw new Exception(ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Setup Connection
		/// </summary>
		/// <remarks>
		/// This method is used to setup the connection objects appropriately
		/// </remarks>
		public void SetupConnection()
		{
			// Declare the required variables

			// Reset all the connections
			if (this.sqlConnection != null) { this.sqlConnection.Dispose(); this.sqlConnection = null; }
			if (this.odbcConnection != null) { this.odbcConnection.Dispose(); this.odbcConnection = null; }
			if (this.sqlCeConnection != null) { this.sqlCeConnection.Dispose(); this.sqlCeConnection = null; }

			// Handle the relevant database type
			switch (this.databaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Create the new SQL Server Connection Object
					this.sqlConnection = new SqlConnection();
					this.sqlConnection.ConnectionString = this.connectionString;

					// Update the Command if required
					if (this.sqlCommand != null) {  this.sqlCommand.Connection = this.sqlConnection; }
					break;

				case CratosDatabaseType.Odbc:
					// Create the new ODBC Connection Object
					this.odbcConnection = new OdbcConnection();
					this.odbcConnection.ConnectionString = this.connectionString;

					// Update the Command if required
					if (this.odbcCommand != null) { this.odbcCommand.Connection = this.odbcConnection; }
					break;

				case CratosDatabaseType.SqlCeServer:
					// Create the new SQL Server CE Connection Object
					this.sqlCeConnection = new SqlCeConnection();
					this.sqlCeConnection.ConnectionString = this.connectionString;

					// Update the Command if required
					if (this.sqlCeCommand != null) { this.sqlCeCommand.Connection = this.sqlCeConnection; }
					break;

				default:
					throw new Exception(ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Execute Non Query
		/// </summary>
		/// <remarks>
		/// This method is used to execute a stored procedure where no results is expected.
		/// </remarks>
		public void ExecuteNonQuery()
		{
			// Declare the required variables

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.sqlCommand == null) { this.SetupCommand(); }
						if (this.sqlDataReader != null) { this.sqlDataReader.Close(); }

						// Open the connection if required
						if (this.sqlCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.sqlCommand.Connection.State != ConnectionState.Closed)
						{
							// Execute the command
							this.sqlCommand.ExecuteNonQuery();
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the SQL Server Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				case CratosDatabaseType.Odbc:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.odbcCommand == null) { this.SetupCommand(); }
						if (this.odbcDataReader != null) { this.odbcDataReader.Close(); }

						// Open the connection if required
						if (this.odbcCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.odbcCommand.Connection.State != ConnectionState.Closed)
						{
							// Execute the command
							this.odbcCommand.ExecuteNonQuery();
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the ODBC Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (OdbcException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				case CratosDatabaseType.SqlCeServer:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.sqlCeCommand == null) { this.SetupCommand(); }
						if (this.sqlCeDataReader != null) { this.sqlCeDataReader.Close(); }

						// Open the connection if required
						if (this.sqlCeCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.sqlCeCommand.Connection.State != ConnectionState.Closed)
						{
							// Execute the command
							this.sqlCeCommand.ExecuteNonQuery();
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the SQL Server CE Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlCeException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Execute the query and return a Data Set
		/// </summary>
		/// <remarks>
		/// This method is used to execute the stored procedure and return the result as a 
		/// dataset to the calling method.
		/// </remarks>
		/// <returns>
		/// This method returns a dataset with the relevant data
		/// </returns>
		public DataSet ExecuteDataSet()
		{
			// Declare the required variables
			DataSet						returnValue;
			SqlDataAdapter		sqlDataAdapter;
			OdbcDataAdapter		odbcDataAdapter;
			SqlCeDataAdapter	sqlCeDataAdapter;

			// Create and Setup the relevant objects
			returnValue        = new DataSet();
			returnValue.Locale = CultureInfo.CurrentCulture;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					try
					{
						// Create the SQL Data Adapter
						sqlDataAdapter = new SqlDataAdapter(this.sqlCommand);

						// Fill the data adapter
						sqlDataAdapter.Fill(returnValue);
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}


					break;

				case CratosDatabaseType.Odbc:
					try
					{
						// Create the SQL Data Adapter
						odbcDataAdapter = new OdbcDataAdapter(this.odbcCommand);

						// Fill the data adapter
						odbcDataAdapter.Fill(returnValue);
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (OdbcException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				case CratosDatabaseType.SqlCeServer:
					try
					{
						// Create the SQL Server CE Data Adapter
						sqlCeDataAdapter = new SqlCeDataAdapter(this.sqlCeCommand);

						// Fill the data adapter
						sqlCeDataAdapter.Fill(returnValue);
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlCeException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Execute the query and return an object
		/// </summary>
		/// <remarks>
		/// This method is used to execute the stored procedure and return the value of the 
		/// first row, the first column to the calling method.
		/// </remarks>
		/// <returns>
		/// This method returns an object with the relevant data
		/// </returns>
		public object ExecuteScalar()
		{
			// Declare the required variables
			object returnValue = null;

			// Make sure the connection is open
			if (this.Connect())
			{
				// Handle the relevant database type
				switch (this.DatabaseType)
				{
					case CratosDatabaseType.SqlServer:
						try
						{
							// Execute the stored procedure
							returnValue = this.sqlCommand.ExecuteScalar();
						}
						catch (TimeoutException)
						{
							this.databaseResult = CratosDatabaseResult.Timeout;
						}
						catch (SqlException sqlEx)
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw sqlEx;
						}

						break;

					case CratosDatabaseType.Odbc:
						try
						{
							// Execute the stored procedure
							returnValue = this.odbcCommand.ExecuteScalar();
						}
						catch (TimeoutException)
						{
							this.databaseResult = CratosDatabaseResult.Timeout;
						}
						catch (OdbcException sqlEx)
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw sqlEx;
						}

						break;

					case CratosDatabaseType.SqlCeServer:
						try
						{
							// Execute the stored procedure
							returnValue = this.sqlCeCommand.ExecuteScalar();
						}
						catch (TimeoutException)
						{
							this.databaseResult = CratosDatabaseResult.Timeout;
						}
						catch (SqlCeException sqlEx)
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw sqlEx;
						}

						break;

					default:
						throw new Exception(CratosDataAccess.ErrorDBUnsupported);
				}

				// Close the connection
				this.Disconnect();
			}
			else
			{
				// Throw an exception
				throw new Exception("Unable to open connection to Database");
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Execute Query and setup the DataReader
		/// </summary>
		/// <remarks>
		/// This method is used to execute the specified SQL Query against the selected
		/// data source and populate the data reader
		/// </remarks>
		public void ExecuteReader()
		{
			// Declare the required variables

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.sqlCommand == null) { this.SetupCommand(); }
						if (this.sqlDataReader != null) { this.sqlDataReader.Close(); }

						// Open the connection if required
						if (this.sqlCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.sqlCommand.Connection.State != ConnectionState.Closed)
						{
							// Update the Command Timeout
							this.sqlCommand.CommandTimeout = this.CommandTimeout;

							// Execute the command
							this.sqlDataReader = this.sqlCommand.ExecuteReader();

							// Perform a read if rows have been returned
							if (this.sqlDataReader.HasRows) { this.sqlDataReader.Read(); }
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the SQL Server Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				case CratosDatabaseType.Odbc:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.odbcCommand == null) { this.SetupCommand(); }
						if (this.odbcDataReader != null) { this.odbcDataReader.Close(); }

						// Open the connection if required
						if (this.odbcCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.odbcCommand.Connection.State != ConnectionState.Closed)
						{
							// Execute the command
							this.odbcDataReader = this.odbcCommand.ExecuteReader();

							// Perform a read if rows have been returned
							if (this.odbcDataReader.HasRows) { this.odbcDataReader.Read(); }
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the ODBC Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (OdbcException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				case CratosDatabaseType.SqlCeServer:
					try
					{
						// Make sure the Command has been setup and the Data reader closed
						if (this.sqlCeCommand == null) { this.SetupCommand(); }
						if (this.sqlCeDataReader != null) { this.sqlCeDataReader.Close(); }

						// Open the connection if required
						if (this.sqlCeCommand.Connection.State == ConnectionState.Closed) { this.Connect(); }

						// Make sure we have a connection
						if (this.sqlCeCommand.Connection.State != ConnectionState.Closed)
						{
							// Execute the command
							this.sqlCeDataReader = this.sqlCeCommand.ExecuteReader();
						}
						else
						{
							this.databaseResult = CratosDatabaseResult.Exception;
							throw new Exception("Unable to connect to the ODBC Database");
						}
					}
					catch (TimeoutException)
					{
						this.databaseResult = CratosDatabaseResult.Timeout;
					}
					catch (SqlCeException sqlEx)
					{
						this.databaseResult = CratosDatabaseResult.Exception;
						throw sqlEx;
					}

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Advance to next record in Data Reader
		/// </summary>
		/// <remarks>
		/// This method is used to advance to the next record in the data reader.
		/// </remarks>
		/// <returns>
		/// A boolean is reurned indicating the success of the method
		/// </returns>
		public bool ReaderRead()
		{
			// Declare the required variables
			bool returnValue = false;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with before advancing to the next record
					if (this.sqlDataReader != null) { returnValue = this.sqlDataReader.Read(); }

					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with before advancing to the next record
					if (this.odbcDataReader != null) { returnValue = this.odbcDataReader.Read(); }

					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with before advancing to the next record
					if (this.sqlCeDataReader != null) { returnValue = this.sqlCeDataReader.Read(); }

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Determine if the reader contains the specified field
		/// </summary>
		/// <param name="fieldName">Field name</param>
		/// <returns>
		/// A boolean value is returned indicating if the field contains a null value
		/// </returns>
		public bool ReaderContainsField(string fieldName)
		{
			// Declare the required variables
			bool returnValue = false;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the field exists
						try { returnValue = (this.sqlDataReader.GetOrdinal(fieldName) >= 0); }
						catch (IndexOutOfRangeException) { }
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the field exists
						try { returnValue = (this.odbcDataReader.GetOrdinal(fieldName) >= 0); }
						catch (IndexOutOfRangeException) { }
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the field exists
						try { returnValue = (this.sqlCeDataReader.GetOrdinal(fieldName) >= 0); }
						catch (IndexOutOfRangeException) { }
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Determine if field in reader is null
		/// </summary>
		/// <remarks>
		/// This method is used to determine whether the specified field in a data reader
		/// contains a null value or not
		/// </remarks>
		/// <param name="fieldName">Field name</param>
		/// <returns>
		/// A boolean value is returned indicating if the field contains a null value
		/// </returns>
		public bool ReaderIsFieldNull(string fieldName)
		{
			// Declare the required variables
			bool returnValue = false;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Advance to the next record
						returnValue = this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName));
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Advance to the next record
						returnValue = this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName));
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Advance to the next record
						returnValue = this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName));
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <param name="dbType">Database type</param>
		/// <returns>
		/// An object is returned that represents the value of the field specified
		/// </returns>
		public object ReaderGetValue(string fieldName, DbType dbType)
		{
			// Declare the required variables
			object returnValue = null;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.sqlDataReader.GetValue(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.odbcDataReader.GetValue(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.sqlCeDataReader.GetValue(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <returns>
		/// An object is returned that represents the value of the field specified
		/// </returns>
		public object ReaderGetValue(string fieldName)
		{
			// Declare the required variables
			object returnValue = null;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.sqlDataReader.GetValue(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.odbcDataReader.GetValue(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							returnValue = this.sqlCeDataReader.GetValue(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve int16 value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <returns>
		/// An int is returned that represents the value of the field specified
		/// </returns>
		public int ReaderGetInt16Value(string fieldName)
		{
			// Declare the required variables
			int returnValue = 0;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlDataReader.GetInt16(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.odbcDataReader.GetInt16(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlCeDataReader.GetInt16(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve int32 value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <returns>
		/// An int is returned that represents the value of the field specified
		/// </returns>
		public int ReaderGetInt32Value(string fieldName)
		{
			// Declare the required variables
			int returnValue = 0;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlDataReader.GetInt32(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.odbcDataReader.GetInt32(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlCeDataReader.GetInt32(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve Int64 value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <returns>
		/// An int is returned that represents the value of the field specified
		/// </returns>
		public long ReaderGetInt64Value(string fieldName)
		{
			// Declare the required variables
			long returnValue = 0;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlDataReader.GetInt64(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.odbcDataReader.GetInt64(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlCeDataReader.GetInt64(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Retrieve double value from the data reader
		/// </summary>
		/// <remarks>
		/// This method is used to retrieve a column value from the data reader object after
		/// a successful execution of the <ref>ExecuteReader</ref> method.
		/// </remarks>
		/// <param name="fieldName">Field Name</param>
		/// <returns>
		/// A double is returned that represents the value of the field specified
		/// </returns>
		public double ReaderGetDoubleValue(string fieldName)
		{
			// Declare the required variables
			double returnValue = 0;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure we have data to work with
					if (this.sqlDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlDataReader.IsDBNull(this.sqlDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlDataReader.GetDouble(this.sqlDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.Odbc:
					// Make sure we have data to work with
					if (this.odbcDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.odbcDataReader.IsDBNull(this.odbcDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.odbcDataReader.GetDouble(this.odbcDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure we have data to work with
					if (this.sqlCeDataReader != null)
					{
						// Determine if the value is null or not
						if (!this.sqlCeDataReader.IsDBNull(this.sqlCeDataReader.GetOrdinal(fieldName)))
						{
							// Retrieve the appropiate field
							returnValue = this.sqlCeDataReader.GetDouble(this.sqlCeDataReader.GetOrdinal(fieldName));
						}
					}
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Clear Stored Procedure Parameters
		/// </summary>
		/// <remarks>
		/// This method is used to clear the stored procedure paramter list.
		/// </remarks>
		public void ClearParameters()
		{
			// Declare the required variables

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure the Command has been setup
					if (this.sqlCommand == null) { this.SetupCommand(); }

					// Clear the relevant parameters
					this.sqlCommand.Parameters.Clear();
					break;

				case CratosDatabaseType.Odbc:
					// Make sure the Command has been setup
					if (this.odbcCommand == null) { this.SetupCommand(); }

					// Clear the relevant parameters
					this.odbcCommand.Parameters.Clear();
					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure the Command has been setup
					if (this.sqlCeCommand == null) { this.SetupCommand(); }

					// Clear the relevant parameters
					this.sqlCeCommand.Parameters.Clear();
					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Add a new stored procedure parameter
		/// </summary>
		/// <remarks>
		/// This method is used to add a new stored procedure parameter that will be passed to the
		/// stored procedure on execution.
		/// </remarks>
		/// <param name="parameterName">Parameter Name</param>
		/// <param name="parameterValue">Parameter value</param>
		public void AddParameter(string parameterName, object parameterValue)
		{
			// Declare the required variables
			SqlParameter		sqlParameter;
			OdbcParameter		odbcParameter;
			SqlCeParameter	sqlCeParameter;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure the Command has been setup
					if (this.sqlCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					sqlParameter = new SqlParameter(parameterName, parameterValue);

					// Add the required parameter
					this.sqlCommand.Parameters.Add(sqlParameter);

					break;

				case CratosDatabaseType.Odbc:
					// Make sure the Command has been setup
					if (this.odbcCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					odbcParameter = new OdbcParameter(parameterName, parameterValue);

					// Add the required parameter
					this.odbcCommand.Parameters.Add(odbcParameter);

					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure the Command has been setup
					if (this.sqlCeCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					sqlCeParameter = new SqlCeParameter(parameterName, parameterValue);

					// Add the required parameter
					this.sqlCeCommand.Parameters.Add(sqlCeParameter);

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Add a new stored procedure parameter
		/// </summary>
		/// <remarks>
		/// This method is used to add a new stored procedure parameter that will be passed to the
		/// stored procedure on execution.
		/// </remarks>
		/// <param name="parameterName">Parameter Name</param>
		/// <param name="dbType">Parameter database type</param>
		/// <param name="parameterValue">Parameter value</param>
		public void AddParameter(string parameterName, DbType dbType, object parameterValue)
		{
			// Make sure the parametervalue has valid value
			if (parameterValue == null) { parameterValue = DBNull.Value; }

			// Call the main method
			this.AddParameter(parameterName, dbType, parameterValue, ParameterDirection.Input);
		}

		/// <summary>
		/// Add a new stored procedure parameter
		/// </summary>
		/// <remarks>
		/// This method is used to add a new stored procedure parameter that will be passed to the
		/// stored procedure on execution.
		/// </remarks>
		/// <param name="parameterName">Parameter Name</param>
		/// <param name="dbType">Parameter database type</param>
		/// <param name="parameterValue">Parameter value</param>
		/// <param name="parameterDirection">Parameter direction</param>
		public void AddParameter(string parameterName, DbType dbType,
														 object parameterValue, ParameterDirection parameterDirection)
		{
			// Declare the required variables
			SqlParameter		sqlParameter;
			OdbcParameter		odbcParameter;
			SqlCeParameter	sqlCeParameter;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure the Command has been setup
					if (this.sqlCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					sqlParameter = new SqlParameter();
					sqlParameter.ParameterName = parameterName;

					if (dbType == DbType.Object) { sqlParameter.SqlDbType = SqlDbType.Image; }
					else { sqlParameter.DbType = dbType; }

					sqlParameter.Direction = parameterDirection;
					sqlParameter.Value = parameterValue;

					// Add the required parameter
					this.sqlCommand.Parameters.Add(sqlParameter);

					break;

				case CratosDatabaseType.Odbc:
					// Make sure the Command has been setup
					if (this.odbcCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					odbcParameter               = new OdbcParameter();
					odbcParameter.ParameterName = parameterName;
					odbcParameter.DbType        = dbType;
					odbcParameter.Direction     = parameterDirection;
					odbcParameter.Value         = parameterValue;

					// Add the required parameter
					this.odbcCommand.Parameters.Add(odbcParameter);

					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure the Command has been setup
					if (this.sqlCeCommand == null) { this.SetupCommand(); }

					// Create and Setup the new SQL Parameter
					sqlCeParameter               = new SqlCeParameter();
					sqlCeParameter.ParameterName = parameterName;
					sqlCeParameter.DbType        = dbType;
					sqlCeParameter.Direction     = parameterDirection;
					sqlCeParameter.Value         = parameterValue;

					// Add the required parameter
					this.sqlCeCommand.Parameters.Add(sqlCeParameter);

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Add a new stored procedure parameter
		/// </summary>
		/// <remarks>
		/// This method is used to add a new stored procedure parameter that will be passed to the
		/// stored procedure on execution.
		/// </remarks>
		/// <param name="parameterName">Parameter Name</param>
		/// <param name="dbType">Parameter database type</param>
		/// <param name="parameterValue">Parameter value</param>
		/// <param name="parameterDirection">Parameter direction</param>
		public void AddSqlParameter(string parameterName, SqlDbType dbType,
																object parameterValue, ParameterDirection parameterDirection)
		{
			// Declare the required variables
			SqlParameter sqlParameter;

			// Handle the relevant database type
			if (this.DatabaseType == CratosDatabaseType.SqlServer)
			{
				// Make sure the Command has been setup
				if (this.sqlCommand == null) { this.SetupCommand(); }

				// Create and Setup the new SQL Parameter
				sqlParameter               = new SqlParameter();
				sqlParameter.ParameterName = parameterName;
				sqlParameter.SqlDbType     = dbType;
				sqlParameter.Direction     = parameterDirection;
				sqlParameter.Value         = parameterValue;

				// Add the required parameter
				this.sqlCommand.Parameters.Add(sqlParameter);
			}
			else
			{
				throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Retrieve a specific parameter value
		/// </summary>
		/// <param name="parameterName">Name of the parameter</param>
		/// <returns>
		/// An object is returned that contains the value of the specified parameter.
		/// </returns>
		public object GetParameterValue(string parameterName)
		{
			// Declare the required variables
			object returnValue = null;

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Make sure the Command has been setup
					if (this.sqlCommand == null) { this.SetupCommand(); }

					// Retrieve the value of the specified parameter
					returnValue = this.sqlCommand.Parameters[parameterName].Value;

					break;

				case CratosDatabaseType.Odbc:
					// Make sure the Command has been setup
					if (this.odbcCommand == null) { this.SetupCommand(); }

					// Retrieve the value of the specified parameter
					returnValue = this.odbcCommand.Parameters[parameterName].Value;

					break;

				case CratosDatabaseType.SqlCeServer:
					// Make sure the Command has been setup
					if (this.sqlCeCommand == null) { this.SetupCommand(); }

					// Retrieve the value of the specified parameter
					returnValue = this.sqlCeCommand.Parameters[parameterName].Value;

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Setup Command
		/// </summary>
		public virtual void SetupCommand()
		{
			// Declare the required variables

			// Make sure only selected Command is active
			if (this.sqlCommand != null) { this.sqlCommand.Dispose(); this.sqlCommand = null; }
			if (this.odbcCommand != null) { this.odbcCommand.Dispose(); this.odbcCommand = null; }

			// Handle the relevant database type
			switch (this.DatabaseType)
			{
				case CratosDatabaseType.SqlServer:
					// Create the appropiate Command Object
					this.sqlCommand									= new SqlCommand();
					this.sqlCommand.Connection			= (SqlConnection)this.Connection;
					this.sqlCommand.CommandText			= this.DBActionText;
					this.sqlCommand.CommandTimeout	= this.CommandTimeout;

					// Handle the DB Action Type
					if (this.DBActionType == DOCratosActionType.StoredProcedure)
					{
						this.sqlCommand.CommandType = CommandType.StoredProcedure;
					}
					else
					{
						// Setup the appropiate Command Object
						this.sqlCommand.CommandType = CommandType.Text;
					}

					break;

				case CratosDatabaseType.Odbc:
					// Create the appropiate Command Object
					this.odbcCommand								= new OdbcCommand();
					this.odbcCommand.Connection			= (OdbcConnection)this.Connection;
					this.odbcCommand.CommandText		= this.DBActionText;
					this.odbcCommand.CommandTimeout = this.commandTimeout;

					// Handle the DB Action Type
					if (this.DBActionType == DOCratosActionType.StoredProcedure)
					{
						this.odbcCommand.CommandType = CommandType.StoredProcedure;
					}
					else
					{
						// Setup the appropiate Command Object
						this.odbcCommand.CommandType = CommandType.Text;
					}

					break;

				case CratosDatabaseType.SqlCeServer:
					// Create the appropiate Command Object
					this.sqlCeCommand             = new SqlCeCommand();
					this.sqlCeCommand.Connection  = (SqlCeConnection)this.Connection;
					this.sqlCeCommand.CommandText = this.DBActionText;

					// Handle the DB Action Type
					if (this.DBActionType == DOCratosActionType.StoredProcedure)
					{
						this.sqlCeCommand.CommandType = CommandType.StoredProcedure;
					}
					else
					{
						// Setup the appropiate Command Object
						this.sqlCeCommand.CommandType = CommandType.Text;
					}

					break;

				default:
					throw new Exception(CratosDataAccess.ErrorDBUnsupported);
			}

			// Return to calling method
			return;
		}
		#endregion

		#region Class Support Methods
		#endregion
	}
}
